﻿using System.Collections.Generic;
using RimWorld;
using UnityEngine;
using Verse;

namespace RI_Talisman
{
    public static class ImPowerFoundationUtility
    {
        public static List<ImFormationArea> tmpImFormationAreas = new List<ImFormationArea>();

        public static List<ImFormationArea> GetFormZones(Map map)
        {
            tmpImFormationAreas.Clear();
            foreach (Thing item in map.listerThings.ThingsOfDef(RI_T_DefOfs.ImPowerFoundation))
            {
                CompImPowerFoundation compImPowerFoundation = item.TryGetComp<CompImPowerFoundation>();
                if (compImPowerFoundation == null || item.Faction != Faction.OfPlayer)
                {
                    continue;
                }
                foreach (ImFormationArea formArea in compImPowerFoundation.FormAreas)
                {
                    if (formArea.Active && !tmpImFormationAreas.Contains(formArea))
                    {
                        formArea.RecalculateBlockingThing();
                        tmpImFormationAreas.Add(formArea);
                    }
                }
            }
            return tmpImFormationAreas;
        }

        public static void DrawLinesToNearbyFoundations(ThingDef myDef, IntVec3 myPos, Rot4 myRot, Map map, Thing thing = null)
        {
            Vector3 a = GenThing.TrueCenter(myPos, myRot, myDef.size, myDef.Altitude);
            foreach (Thing item in map.listerThings.ThingsOfDef(RI_T_DefOfs.ImPowerFoundation))
            {
                if ((thing == null || thing != item) && item.Faction == Faction.OfPlayer)
                {
                    CompImPowerFoundation compImPowerFoundation = item.TryGetComp<CompImPowerFoundation>();
                    if (compImPowerFoundation != null && CanLinkTo(myPos, compImPowerFoundation) && !GenThing.CloserThingBetween(myDef, myPos, item.Position, map))
                    {
                        GenDraw.DrawLineBetween(a, item.TrueCenter(), SimpleColor.White);
                    }
                }
            }
            float minEdgeDistance = myDef.GetCompProperties<CompProperties_ImPowerFoundation>().edgeLengthRange.min - 1f;
            float maxEdgeDistance = myDef.GetCompProperties<CompProperties_ImPowerFoundation>().edgeLengthRange.max - 1f;
            foreach (Thing item2 in map.listerThings.ThingsInGroup(ThingRequestGroup.Blueprint))
            {
                if ((thing == null || thing != item2) && item2.def.entityDefToBuild == myDef && (myPos.x == item2.Position.x || myPos.z == item2.Position.z) && !AlignedDistanceTooShort(myPos, item2.Position, minEdgeDistance) && !AlignedDistanceTooLong(myPos, item2.Position, maxEdgeDistance) && !GenThing.CloserThingBetween(myDef, myPos, item2.Position, map))
                {
                    GenDraw.DrawLineBetween(a, item2.TrueCenter(), SimpleColor.White);
                }
            }
        }

        public static bool AlignedDistanceTooShort(IntVec3 position, IntVec3 otherPos, float minEdgeDistance)
        {
            if (position.x == otherPos.x)
            {
                return (float)Mathf.Abs(position.z - otherPos.z) < minEdgeDistance;
            }
            if (position.z == otherPos.z)
            {
                return (float)Mathf.Abs(position.x - otherPos.x) < minEdgeDistance;
            }
            return false;
        }

        private static bool AlignedDistanceTooLong(IntVec3 position, IntVec3 otherPos, float maxEdgeDistance)
        {
            if (position.x == otherPos.x)
            {
                return (float)Mathf.Abs(position.z - otherPos.z) >= maxEdgeDistance;
            }
            if (position.z == otherPos.z)
            {
                return (float)Mathf.Abs(position.x - otherPos.x) >= maxEdgeDistance;
            }
            return false;
        }

        public static bool CanLinkTo(IntVec3 position, CompImPowerFoundation other)
        {
            if (position.x == other.parent.Position.x)
            {
                return other.parent.def.displayNumbersBetweenSameDefDistRange.Includes(Mathf.Abs(position.z - other.parent.Position.z) + 1);
            }
            if (position.z == other.parent.Position.z)
            {
                return other.parent.def.displayNumbersBetweenSameDefDistRange.Includes(Mathf.Abs(position.x - other.parent.Position.x) + 1);
            }
            return false;
        }
            }
}